home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-25 | 31.7 KB | 1,012 lines |
- /* FTP client (interactive user) code */
- #define LINELEN 128 /* Length of command buffer */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <stdarg.h>
- #include "dbox.h"
- #include "werr.h"
- #include "global.h"
- #include "mbuf.h"
- #include "netuser.h"
- #include "icmp.h"
- #include "timer.h"
- #include "tcp.h"
- #include "ftp.h"
- #include "session.h"
- #include "cmdparse.h"
- #include "misc.h"
- #include "domain.h"
-
- static struct ftpcmds {
- char *name;
- int (*func)();
- int argcmin;
- char *argc_errmsg;
- char *help_msg;
- };
-
- extern char nospace[];
- extern char badhost[];
- static char prompt[] = "ftp> ";
- static char notsess[] = "Not an FTP session!\n";
- static char cantwrite[] = "Can't write %s\n";
- static char cantread[] = "Can't read %s\n";
- static struct session *current;
-
- static int ftp(int32, char *, char *, char *, struct session *);
- static int ftp_error(char *, char *, struct session *);
- static int ftpcmdparse(struct ftpcmds *, char *);
- static int docd(int, char **);
- static int docdup(int, char **);
- static int domkdir(int, char **);
- static int dormdir(int, char **);
- static int doascii(int, char **);
- static int dobinary(int, char **);
- static int dohelp(int, char **);
- static int dotype(int, char **);
- static int doget(int, char **);
- static int dopwd(int, char **);
- static int dobell(int, char **);
- static int dodelete(int, char **);
- static int dohash(int, char **);
- static int dolist(int, char **);
- static int dols(int, char **);
- static int doput(int, char **);
- static int doquit(int, char **);
- static int doquote(int, char **);
- static int douser(int, char **);
- static int dopass(int, char **);
- static int dorhelp(int, char **);
- static int dosystem(int, char **);
- static void doreply(struct ftp *);
- static void ftpsetup(struct ftp *, void (*)(), void (*)(), void (*)());
- static void ftpccs(struct tcb *, char, char);
- static void ftpcds(struct tcb *, char, char);
- static int sndftpmsg(struct ftp *, char *, ...);
-
- #define FTP_Connect 0
- #define FTP_Host 1
-
- static struct ftpcmds ftpabort[] = {
- {"abort", doabort, 0, NULLCHAR, NULLCHAR},
- {NULLCHAR, NULLFP, 0, NULLCHAR, NULLCHAR}
- };
-
- static struct ftpcmds ftpcmds[] = {
- {"ascii", doascii, 0, NULLCHAR, "set ascii transfer type"},
- {"bell", dobell, 0, NULLCHAR, "beep when command completed"},
- {"binary", dobinary, 0, NULLCHAR, "set binary transfer type"},
- {"bye", doquit, 0, NULLCHAR, "terminate ftp session and quit"},
- {"cd", docd, 2, "cd <directory>\n", "change remote working directory"},
- {"cdup", docdup, 0, NULLCHAR, "change remote working directory to parent directory"},
- {"delete", dodelete, 2, "delete <remotefile>\n","delete remote file"},
- {"dir", dolist, 0, NULLCHAR, "list contents of remote directory"},
- {"get", doget, 2, "get remotefile [localfile]\n","recive file"},
- {"hash", dohash, 0, NULLCHAR, "toggle printing '#' for each buffer transferred"},
- {"help", dohelp, 0, NULLCHAR, "print local help information"},
- {"image", dobinary, 0, NULLCHAR, "set binary transfer mode"},
- {"list", dolist, 0, NULLCHAR, "list contents of remote directory"},
- {"ls", dols, 0, NULLCHAR, "nlist contents of remote directory"},
- {"mkdir", domkdir, 2, "mkdir <directory>\n", "make directory on the remote machine"},
- {"nlist", dols, 0, NULLCHAR, "nlist contents of remote directory"},
- {"pass", dopass, 2, "pass <password>\n", "send password to remote system"},
- {"put", doput, 2, "put localfile [remotefile]\n","send one file"},
- {"pwd", dopwd, 0, NULLCHAR, "print working directory on remote machine"},
- {"quit", doquit, 0, NULLCHAR, "terminate ftp session and exit"},
- {"quote", doquote, 2, "quote <arguments>\n", "send arbitrary ftp command"},
- {"recv", doget, 2, "recv remotefile [localfile]\n","receive file"},
- {"remotehelp",dorhelp,0, NULLCHAR, "get help from remote server"},
- {"rhelp", dorhelp, 0, NULLCHAR, "get help from remote server"},
- {"rmdir", dormdir, 2, "rmdir <directory>\n", "remove directory on the remote machine"},
- {"send", doput, 2, "send localfile [remotefile]\n","send one file"},
- {"system", dosystem, 0, NULLCHAR, "show remote system type"},
- {"type", dotype, 0, NULLCHAR, "set file transfer type"},
- {"user", douser, 2, "user <username>\n", "send new user information"},
- {"?", dohelp, 0, NULLCHAR, "print local help information"},
- {NULLCHAR, NULLFP, 0, NULLCHAR, NULLCHAR}
- };
-
- void start_ftp(void)
- {
- struct session *session;
- char buffer[80];
- char Host[256];
- dbox d;
-
- if ((d = dbox_new("FTP")) == NULL)
- return;
-
- dbox_setfield(d, FTP_Host, "");
- dbox_show(d);
-
- if (dbox_fillin(d) == FTP_Connect)
- {
- dbox_getfield(d, FTP_Host, Host, 255);
-
- /* Allocate a session descriptor */
- sprintf(buffer, "FTP - %.60s", Host);
- if ((session = newsession(buffer)) == NULLSESSION)
- {
- werr(0, "Too many sessions");
- return;
- }
-
- session->name = strdup(Host);
- session->type = RESOLVING;
- session->parse = NULLVFP;
-
- sprintf(buffer, "Resolving %.60s ...\n", Host);
- Window_Write(session->window, buffer, strlen(buffer));
-
- resolve_a(Host, NULLCHAR, NULLCHAR, session, ftp, ftp_error);
- }
-
- dbox_dispose(&d);
- }
-
- static int ftp_error(char *host, char *message, struct session *s)
- {
- char buffer[80];
-
- sprintf(buffer, "Cannot FTP to %s - %s\n", host, message);
- Window_Write(s->window, buffer, strlen(buffer));
-
- detachsession(s);
-
- return 0;
- }
-
- /* Handle top-level FTP command */
- static int ftp(int32 address, char *host, char *arg1, char *arg2, struct session *s)
- {
- char buffer[80];
- struct ftp *ftp;
- struct tcb *tcb;
- struct socket lsocket, fsocket;
-
- host = host;
- arg1 = arg1;
- arg2 = arg2;
-
- lsocket.address = ip_addr;
- lsocket.port = lport++;
-
- fsocket.address = address;
- fsocket.port = FTP_PORT;
-
- s->type = FTP;
- s->addr = fsocket.address;
- s->parse = ftpparse;
- s->echo = 1;
- s->raw = 0;
-
- /* Allocate an FTP control block */
- if((ftp = ftp_create(LINELEN)) == NULLFTP){
- Window_Write(s->window, nospace, strlen(nospace));
- detachsession(s);
- return 1;
- }
- ftp->state = STARTUP_STATE;
- ftp->hash = 0;
- ftp->bell = 0;
- s->cb.ftp = ftp; /* Downward link */
- ftp->session = s; /* Upward link */
-
- sprintf(buffer, "Trying [%s] ...\n", inet_ntoa(address));
- Window_Write(s->window, buffer, strlen(buffer));
-
- /* Now open the control connection */
- tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,
- 0,(void(*)())ftpccr,NULLVFP,(void(*)())ftpccs,0,(char *)ftp);
-
- ftp->control = tcb;
-
- return 0;
- }
- /* Parse user FTP commands */
- void ftpparse(struct session *session, char *line, int16 len)
- {
- char buffer[80];
-
- line[len] = '\0';
- current = session;
-
- switch(session->cb.ftp->state){
- case RECEIVING_STATE:
- case SENDING_FILE_STATE:
- /* The only command allowed in data transfer state is ABORT */
- if (ftpcmdparse(ftpabort, line) == -1) {
- Window_Write(session->window, "Transfer in progress; only ABORT is acceptable\n", 47);
- }
- break;
- case COMMAND_STATE:
- if (ftpcmdparse(ftpcmds, line) == -1) {
- Window_Write(session->window, "?Invalid command\n", 17);
- Window_Write(session->window, prompt, strlen(prompt));
- }
- break;
- case STARTUP_STATE: /* Startup up autologin */
- sprintf(buffer,"Not connected yet, ignoring %s\n",line);
- Window_Write(session->window, buffer, strlen(buffer));
- break;
- case USER_STATE: /* Got the user name */
- line[len] = '\0';
- sndftpmsg(session->cb.ftp,"USER %s",line);
- break;
- case PASS_STATE: /* Got the password */
- session->raw = 0;
- line[len] = '\0';
- sndftpmsg(session->cb.ftp,"PASS %s",line);
- break;
- }
- }
-
- static int ftpcmdparse(struct ftpcmds *cmds, char *command)
- {
- struct ftpcmds *cmd;
- int argc = 0;
- char *argv[NARG];
- char *s;
-
- s = strtok(command, " \t\n\r");
-
- while (s != NULLCHAR && argc < NARG)
- {
- argv[argc++] = s;
- s = strtok(NULLCHAR, " \t\n\r");
- }
-
- if (argc == 0)
- {
- Window_Write(current->window,prompt,strlen(prompt));
- return 0;
- }
-
- for (cmd = cmds; cmd->name != NULLCHAR; cmd++)
- {
- if (strncmp(cmd->name, argv[0], strlen(argv[0])) == 0)
- {
- if (argc < cmd->argcmin)
- {
- Window_Write(current->window,cmd->argc_errmsg,strlen(cmd->argc_errmsg));
- Window_Write(current->window,prompt,strlen(prompt));
- return 0;
- }
- else
- {
- (*cmd->func)(argc, argv);
- return 0;
- }
- }
- }
-
- return -1;
- }
- /* Translate 'cd' to 'cwd' for convenience */
- static int docd(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"CWD %s\r\n",argv[1]);
- }
- /* Translate 'cd' to 'cwd' for convenience */
- static int docdup(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"CDUP\r\n");
- }
- /* Translate 'delete' to 'dele' for convenience */
- static int dodelete(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"DELE %s\r\n",argv[1]);
- }
- /* Translate 'pwd' to 'pwd' for convenience */
- static int dopwd(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"PWD\r\n");
- }
- /* Translate 'rmdir' to 'rmd' for convenience */
- static int dormdir(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"RMD %s\r\n",argv[1]);
- }
- /* Translate 'mkdir' to 'mkd' for convenience */
- static int domkdir(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"MKD %s\r\n",argv[1]);
- }
- static int dobinary(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- ftp->type = IMAGE_TYPE;
- sndftpmsg(ftp,"TYPE I\r\n");
-
- return(0);
- }
- static int doascii(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
- ftp->type = ASCII_TYPE;
- sndftpmsg(ftp,"TYPE A\r\n");
-
- return(0);
- }
- static int dorhelp(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- sndftpmsg(ftp,"HELP\r\n");
-
- return(0);
- }
- static int dosystem(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"SYST\r\n");
- }
- static int doquote(int argc, char **argv)
- {
- char buffer[80];
- register struct ftp *ftp;
- int i;
-
- ftp = current->cb.ftp;
-
- *buffer = '\0';
- for (i = 1; i < argc; i++)
- {
- strcat(buffer, argv[i]);
- strcat(buffer, " ");
- }
-
- strcat(buffer, "\r\n");
-
- return sndftpmsg(ftp, buffer);
- }
- static int dohash(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- ftp->hash = !ftp->hash;
-
- if (ftp->hash)
- Window_Write(ftp->session->window,"Hash mark printing on (1024 bytes/hash mark).\n",46);
- else
- Window_Write(ftp->session->window,"Hash mark printing off\n",23);
-
- Window_Write(ftp->session->window, prompt, strlen(prompt));
-
- return(0);
- }
-
- static int dobell(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- ftp->bell = !ftp->bell;
-
- if (ftp->bell)
- Window_Write(ftp->session->window,"Bell mode on\n",13);
- else
- Window_Write(ftp->session->window,"Bell mode off\n",14);
-
- Window_Write(ftp->session->window, prompt, strlen(prompt));
-
- return(0);
- }
-
- static int dohelp(int argc, char **argv)
- {
- char buffer[80];
- struct ftpcmds *cmd;
- struct ftp *ftp;
- int n;
-
- ftp = current->cb.ftp;
-
- if (argc == 1)
- {
- Window_Write(ftp->session->window, "Commands may be abbreviated. Commands are:\n", 43);
-
- for (n = 0, cmd = ftpcmds; cmd->name != NULLCHAR; cmd++, n++)
- {
- sprintf(buffer, "%c%-13s", (n % 5) ? ' ' : '\n', cmd->name);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- }
-
- Window_Write(ftp->session->window, "\n", 1);
- Window_Write(ftp->session->window, prompt, strlen(prompt));
- }
- else
- {
- for (cmd = ftpcmds; cmd->name != NULLCHAR; cmd++)
- {
- if (strncmp(cmd->name, argv[1], strlen(argv[1])) == 0)
- {
- sprintf(buffer, "%-13s%s\n",cmd->name,cmd->help_msg);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- Window_Write(ftp->session->window, prompt, strlen(prompt));
- return 0;
- }
- }
-
- sprintf(buffer, "?Invalid help command %s\n", argv[1]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- Window_Write(ftp->session->window, prompt, strlen(prompt));
- }
-
- return 0;
- }
-
- static int douser(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"USER %s\r\n",argv[1]);
- }
-
- static int dopass(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"PASS %s\r\n",argv[1]);
- }
-
- /* Handle "type" command from user */
- static int dotype(int argc, char **argv)
- {
- char buffer[100];
- register struct ftp *ftp;
-
- ftp = current->cb.ftp;
- if(argc < 2){
- switch(ftp->type){
- case IMAGE_TYPE:
- Window_Write(ftp->session->window,"Using binary mode to transfer files.\n",37);
- break;
- case ASCII_TYPE:
- Window_Write(ftp->session->window,"Using ascii mode to transfer files.\n",36);
- break;
- }
-
- Window_Write(ftp->session->window, prompt, strlen(prompt));
- return 0;
- }
- switch(*argv[1]){
- case 'i':
- case 'b':
- ftp->type = IMAGE_TYPE;
- sndftpmsg(ftp,"TYPE I\r\n");
- break;
- case 'a':
- ftp->type = ASCII_TYPE;
- sndftpmsg(ftp,"TYPE A\r\n");
- break;
- case 'l':
- ftp->type = IMAGE_TYPE;
- sndftpmsg(ftp,"TYPE L %s\r\n",argv[2]);
- break;
- default:
- sprintf(buffer,"%s: unknown mode\n",argv[1]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- Window_Write(ftp->session->window, prompt, strlen(prompt));
- return 1;
- }
-
- return 0;
- }
- /* Start receive transfer. Syntax: get <remote name> [<local name>] */
- static int doget(int argc, char **argv)
- {
- char buffer[100];
- char *remotename,*localname;
- register struct ftp *ftp;
- char *mode;
-
- ftp = current->cb.ftp;
- if(ftp == NULLFTP){
- werr(0,notsess);
- return 1;
- }
- remotename = argv[1];
- if(argc < 3)
- localname = remotename;
- else
- localname = argv[2];
-
- if(ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
-
- if(ftp->type == IMAGE_TYPE)
- mode = "wb";
- else
- mode = "w";
-
- if((ftp->fp = fopen(localname,mode)) == NULLFILE){
- sprintf(buffer,cantwrite,localname);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- return 1;
- }
- time(&ftp->start);
- ftp->bytes = 0;
- ftp->state = RECEIVING_STATE;
- ftpsetup(ftp,(void(*)())ftpdr,NULLVFP,(void(*)())ftpcds);
-
- /* Generate the command to start the transfer */
- return sndftpmsg(ftp,"RETR %s\r\n",remotename);
- }
- /* List remote directory. Syntax: dir <remote directory/file> [<local name>] */
- static int dolist(int argc, char **argv)
- {
- char buffer[100];
- register struct ftp *ftp;
-
- ftp = current->cb.ftp;
- if(ftp == NULLFTP){
- werr(0,notsess);
- return 1;
- }
- if(ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
-
- if(argc < 3){
- ftp->fp = stdout;
- } else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
- sprintf(buffer,cantwrite,argv[2]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- return 1;
- }
- time(&ftp->start);
- ftp->bytes = 0;
- ftp->state = RECEIVING_STATE;
- ftpsetup(ftp,(void(*)())ftpdr,NULLVFP,(void(*)())ftpcds);
- /* Generate the command to start the transfer
- * It's done this way to avoid confusing the 4.2 FTP server
- * if there's no argument
- */
- if (argc > 1)
- return sndftpmsg(ftp,"LIST %s\r\n",argv[1]);
- else
- return sndftpmsg(ftp,"LIST\r\n","");
- }
- /* Abbreviated (name only) list of remote directory.
- * Syntax: ls <remote directory/file> [<local name>]
- */
- static int dols(int argc, char **argv)
- {
- char buffer[100];
- register struct ftp *ftp;
-
- ftp = current->cb.ftp;
- if(ftp == NULLFTP){
- werr(0,notsess);
- return 1;
- }
- if(ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
-
- if(argc < 3){
- ftp->fp = stdout;
- } else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
- sprintf(buffer,cantwrite,argv[2]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- return 1;
- }
- time(&ftp->start);
- ftp->bytes = 0;
- ftp->state = RECEIVING_STATE;
- ftpsetup(ftp,(void(*)())ftpdr,NULLVFP,(void(*)())ftpcds);
- /* Generate the command to start the transfer */
- if(argc > 1)
- return sndftpmsg(ftp,"NLST %s\r\n",argv[1]);
- else
- return sndftpmsg(ftp,"NLST\r\n","");
- }
- /* Start transmit. Syntax: put <local name> [<remote name>] */
- static int doput(int argc, char **argv)
- {
- char buffer[100];
- char *remotename,*localname;
- char *mode;
- struct ftp *ftp;
-
- if((ftp = current->cb.ftp) == NULLFTP){
- werr(0,notsess);
- return 1;
- }
- localname = argv[1];
- if(argc < 3)
- remotename = localname;
- else
- remotename = argv[2];
-
- if(ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
-
- if(ftp->type == IMAGE_TYPE)
- mode = "rb";
- else
- mode = "r";
-
- if((ftp->fp = fopen(localname,mode)) == NULLFILE){
- sprintf(buffer,cantread,localname);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- return 1;
- }
- time(&ftp->start);
- ftp->bytes = 0;
- ftp->state = SENDING_FILE_STATE;
- ftpsetup(ftp,NULLVFP,(void(*)())ftpdt,(void(*)())ftpcds);
-
- /* Generate the command to start the transfer */
- return sndftpmsg(ftp,"STOR %s\r\n",remotename);
- }
- /* Translate 'bye' and 'quit' to 'quit' for convenience */
- static int doquit(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- return sndftpmsg(ftp,"QUIT\r\n");
- }
- /* Abort a GET or PUT operation in progress. Note: this will leave
- * the partial file on the local or remote system
- */
- int doabort(int argc, char **argv)
- {
- register struct ftp *ftp;
-
- argc = argc;
- argv = argv;
-
- ftp = current->cb.ftp;
-
- /* Close the local file */
- if(ftp->fp != NULLFILE && ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
-
- switch(ftp->state){
- case SENDING_FILE_STATE:
- /* Send a premature EOF.
- * Unfortunately we can't just reset the connection
- * since the remote side might end up waiting forever
- * for us to send something.
- */
- close_tcp(ftp->data);
- Window_Write(ftp->session->window, "Put aborted\n", 12);
- break;
- case RECEIVING_STATE:
- /* Just exterminate the data channel TCB; this will
- * generate a RST on the next data packet which will
- * abort the sender
- */
- del_tcp(ftp->data);
- ftp->data = NULLTCB;
- Window_Write(ftp->session->window, "Get aborted\n", 12);
- break;
- }
- ftp->state = COMMAND_STATE;
- Window_Write(ftp->session->window, prompt, strlen(prompt));
- return 0;
- }
- /* create data port, and send PORT message */
- static void ftpsetup(struct ftp *ftp, void (*recv)(),
- void (*send)(), void (*state)())
- {
- struct socket lsocket;
- struct mbuf *bp;
-
- lsocket.address = ip_addr;
- lsocket.port = lport++;
-
- /* Compose and send PORT a,a,a,a,p,p message */
-
- if((bp = alloc_mbuf(35)) == NULLBUF){ /* 5 more than worst case */
- werr(0,nospace);
- return;
- }
- /* I know, this looks gross, but it works! */
- sprintf(bp->data,"PORT %u,%u,%u,%u,%u,%u\r\n",
- hibyte(hiword(lsocket.address)),
- lobyte(hiword(lsocket.address)),
- hibyte(loword(lsocket.address)),
- lobyte(loword(lsocket.address)),
- hibyte(lsocket.port),
- lobyte(lsocket.port));
- bp->cnt = strlen(bp->data);
- send_tcp(ftp->control,bp);
-
- /* Post a listen on the data connection */
- ftp->data = open_tcp(&lsocket,NULLSOCK,TCP_PASSIVE,0,
- recv,send,state,0,(char *)ftp);
- }
- /* FTP Client Control channel Receiver upcall routine */
- void ftpccr(register struct tcb *tcb, int16 cnt)
- {
- struct mbuf *bp;
- struct ftp *ftp;
- char c;
-
- if((ftp = (struct ftp *)tcb->user) == NULLFTP){
- /* Unknown connection; kill it */
- close_tcp(tcb);
- return;
- }
-
- if(recv_tcp(tcb,&bp,cnt) > 0){
- while(pullup(&bp,&c,1) == 1){
- switch(c){
- case '\r': /* Strip cr's */
- continue;
- case '\n': /* Complete line; process it */
- ftp->buf[ftp->cnt] = '\0';
- doreply(ftp);
- ftp->cnt = 0;
- break;
- default:
- if(ftp->cnt != LINELEN-1)
- ftp->buf[ftp->cnt++] = c;
- break;
- }
- }
- }
- }
-
- /* Process replies from the server */
- static void doreply(register struct ftp *ftp)
- {
- char buffer[80];
- char **s;
-
- sprintf(buffer, "%s\n", ftp->buf);
- Window_Write(ftp->session->window, buffer, strlen(buffer));
-
- if(ftp->cnt < 3) return;
- switch(ftp->state){
- case SENDING_FILE_STATE:
- case RECEIVING_STATE:
- if (ftp->buf[0] == '5') doabort(0, s);
- break;
- case STARTUP_STATE:
- if (strncmp(ftp->buf, "220", 3) == 0){
- ftp->state = USER_STATE;
- Window_Write(ftp->session->window, "Enter user name: ", 17);
- } else {
- ftp->state = COMMAND_STATE;
- }
- break;
- case USER_STATE:
- if (strncmp(ftp->buf, "331", 3) == 0){
- ftp->state = PASS_STATE;
- ftp->session->echo = 0;
- Window_Write(ftp->session->window, "Password: ", 10);
- } else {
- ftp->state = COMMAND_STATE;
- }
- break;
- case PASS_STATE:
- ftp->session->echo = 1;
- ftp->state = COMMAND_STATE;
- Window_Write(ftp->session->window,prompt,strlen(prompt));
- break;
- case COMMAND_STATE:
- if (ftp->buf[0] >= '1' && ftp->buf[0] <= '5' && ftp->buf[3] == ' ')
- Window_Write(ftp->session->window,prompt,strlen(prompt));
- break;
- }
- }
-
- /* FTP Client Control channel State change upcall routine */
- static void ftpccs(register struct tcb *tcb, char old, char new)
- {
- char buffer[40];
- struct ftp *ftp;
- extern char *tcpstates[];
- extern char *reasons[];
- extern char *unreach[];
- extern char *exceed[];
-
- old = old;
-
- /* Can't add a check for unknown connection here, it would loop
- * on a close upcall! We're just careful later on.
- */
- ftp = (struct ftp *)tcb->user;
-
- switch(new){
- case CLOSE_WAIT:
- sprintf(buffer,"%s\n",tcpstates[new]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- close_tcp(tcb);
- break;
- case CLOSED: /* heh heh */
- sprintf(buffer,"%s (%s",tcpstates[new],reasons[tcb->reason]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- if(tcb->reason == NETWORK){
- switch(tcb->type){
- case DEST_UNREACH:
- sprintf(buffer,": %s unreachable",unreach[tcb->code]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- break;
- case TIME_EXCEED:
- sprintf(buffer,": %s time exceeded",exceed[tcb->code]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- break;
- }
- }
- Window_Write(ftp->session->window,")\n",2);
- del_tcp(tcb);
- if(ftp != NULLFTP)
- ftp_delete(ftp);
- break;
- default:
- sprintf(buffer,"%s\n",tcpstates[new]);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- break;
- }
- }
- /* FTP Client Data channel State change upcall handler */
- static void ftpcds(struct tcb *tcb, char old, char new)
- {
- char buffer[80];
- struct ftp *ftp;
- time_t timenow;
- double elapsed;
- double average;
-
- old = old;
-
-
- if((ftp = (struct ftp *)tcb->user) == NULLFTP){
- /* Unknown connection, kill it */
- close_tcp(tcb);
- return;
- }
-
- time(&timenow);
- if ((elapsed = difftime(timenow, ftp->start)) == 0.0) elapsed = 1.0;
- average = (float)ftp->bytes / elapsed;
-
- switch(new){
- case FINWAIT2:
- case TIME_WAIT:
- if(ftp->state == SENDING_FILE_STATE){
- /* We've received an ack of our FIN, so
- * return to command mode
- */
- ftp->state = COMMAND_STATE;
- if (ftp->hash) Window_Write(ftp->session->window,"\n",1);
- if (ftp->bell) Window_Write(ftp->session->window,"\007",1);
- sprintf(buffer,"Put complete, %d bytes sent in %.0f seconds (%.0f bytes/sec)\n",
- ftp->bytes,elapsed,average);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- }
- break;
- case CLOSE_WAIT:
- close_tcp(tcb);
- if(ftp->state == RECEIVING_STATE){
- /* End of file received on incoming file */
- if(ftp->fp != stdout)
- fclose(ftp->fp);
- ftp->fp = NULLFILE;
- ftp->state = COMMAND_STATE;
- if (ftp->hash) Window_Write(ftp->session->window,"\n",1);
- if (ftp->bell) Window_Write(ftp->session->window,"\007",1);
- sprintf(buffer,"Get complete, %d bytes received in %.0f seconds (%.0f bytes/sec)\n",
- ftp->bytes,elapsed,average);
- Window_Write(ftp->session->window,buffer,strlen(buffer));
- }
- break;
- case CLOSED:
- ftp->data = NULLTCB;
- del_tcp(tcb);
- break;
- }
- }
- /* Send a message on the control channel */
- static int sndftpmsg(struct ftp *ftp, char *fmt, ...)
- {
- va_list argptr;
- struct mbuf *bp;
- int16 len;
-
- va_start(argptr,fmt);
- len = strlen(fmt) + strlen(va_arg(argptr,char *)) + 10;
- va_end(argptr);
- if((bp = alloc_mbuf(len)) == NULLBUF){
- Window_Write(ftp->session->window, nospace, strlen(nospace));
- return 1;
- }
- va_start(argptr,fmt);
- vsprintf(bp->data,fmt,argptr);
- va_end(argptr);
- bp->cnt = strlen(bp->data);
- send_tcp(ftp->control,bp);
- return 0;
- }
-